package utils;

import java.util.LinkedList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CustomThreadPool {
    private final int poolSize;
    private final WorkerThread[] threads;
    private final LinkedList<Runnable> taskQueue;

    public CustomThreadPool(int poolSize) {
        this.poolSize = poolSize;
        this.threads = new WorkerThread[poolSize];
        this.taskQueue = new LinkedList<>();

        for (int i = 0; i < poolSize; i++) {
            threads[i] = new WorkerThread();
            threads[i].start();
        }
    }

    public Future<?> submit(Runnable task) {
        CustomFuture future = new CustomFuture();
        synchronized (taskQueue) {
            taskQueue.addLast(() -> {
                try {
                    task.run();
                    future.done(); // 任务执行完成时标记为完成
                } catch (Exception e) {
                    future.setException(e); // 如果任务执行出错，记录异常
                }
            });
            taskQueue.notify(); // 唤醒等待的工作线程
        }
        return future;
    }

    private class WorkerThread extends Thread {
        @Override
        public void run() {
            Runnable task;
            while (true) {
                synchronized (taskQueue) {
                    while (taskQueue.isEmpty()) {
                        try {
                            taskQueue.wait(); // 等待任务被添加到队列
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    task = taskQueue.removeFirst();
                }
                try {
                    task.run(); // 执行任务
                } catch (RuntimeException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void shutdown() {
        for (int i = 0; i < poolSize; i++) {
            threads[i] = null;
        }
    }

    private class CustomFuture implements Future<Object> {
        private volatile boolean isDone = false;
        private Exception exception = null;

        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            return false; // 不支持取消任务
        }

        @Override
        public boolean isCancelled() {
            return false; // 不支持取消任务
        }

        @Override
        public boolean isDone() {
            return isDone;
        }

        @Override
        public Object get() throws InterruptedException {
            synchronized (this) {
                while (!isDone) {
                    wait();
                }
                if (exception != null) {
                    throw new RuntimeException("Task execution failed", exception);
                }
            }
            return null;
        }

        @Override
        public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            synchronized (this) {
                long startTime = System.currentTimeMillis();
                long elapsedTime = 0;
                while (!isDone && elapsedTime < timeout) {
                    try {
                        wait(timeout - elapsedTime);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                    elapsedTime = System.currentTimeMillis() - startTime;
                }
                if (!isDone) {
                    throw new RuntimeException("Task execution timeout");
                }
                if (exception != null) {
                    throw new RuntimeException("Task execution failed", exception);
                }
            }
            return null;
        }

        public void done() {
            synchronized (this) {
                isDone = true;
                notifyAll();
            }
        }

        public void setException(Exception exception) {
            synchronized (this) {
                this.exception = exception;
                isDone = true;
                notifyAll();
            }
        }
    }

}
